#include <cmath>
#include "app/ApplicationConfig.h"
#include "GUIEngine.h"
#include "util/exceptions/ElementNotFoundException.h"
#include "util/MathUtils.h"

namespace gui {

GUIEngine::GUIEngine(int width, int height, int bpp, std::string caption, bool fullScreen) {
	this->screenRect.w = width;
	this->screenRect.h = height;
	this->screenRect.x = 0;
	this->screenRect.y = 0;
	this->screenBPP = bpp;
	this->screenCaption = caption;
	this->fullScreen = fullScreen;
	this->xScale = 1;
	this->yScale = 1;
}

GUIEngine::~GUIEngine() {
	delete this->surfaceFactory;
}

bool GUIEngine::start(bool splashScreen) {
	if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) {
		return false;
	}

	int defaults = SDL_HWSURFACE | SDL_DOUBLEBUF;

	this->screen = SDL_SetVideoMode(this->screenRect.w, this->screenRect.h, this->screenBPP,
			(this->fullScreen) ? defaults | SDL_FULLSCREEN : defaults);

	if (this->screen == NULL) {
		return false;
	}
    this->rColor = app::ApplicationConfig::getOptionalIntProperty("bgColorR", 242);
    this->gColor = app::ApplicationConfig::getOptionalIntProperty("bgColorG", 239);
    this->bColor = app::ApplicationConfig::getOptionalIntProperty("bgColorB", 233);
    this->clearScreen();

    if (splashScreen) this->showSplash();

    SDL_WM_SetCaption(this->screenCaption.c_str(), NULL);

    this->surfaceFactory = new SurfaceFactory(this->screenBPP, this->screen->format->Rmask, this->screen->format->Gmask,
			this->screen->format->Bmask, this->screen->format->Amask);

    return true;
}

void GUIEngine::stop() {
	SDL_FreeSurface(this->screen);
	SDL_QuitSubSystem(SDL_INIT_VIDEO);
	SDL_Quit();
}

void GUIEngine::drawSurface(Surface* surface){
	this->drawSurface(surface->getSurface(), NULL);
}

void GUIEngine::clearScreen() {
	SDL_Rect rect;
	rect.x = 0;
	rect.y = 0;
	rect.w = this->screen->w;
	rect.h = this->screen->h;
	SDL_FillRect(this->screen, &rect, SDL_MapRGB(this->screen->format, this->rColor, this->gColor, this->bColor));
}

int GUIEngine::pollEvent(InputEvent* event) {
	SDL_Event sdlEvent;
	int ret = SDL_PollEvent(&sdlEvent);
	if (ret) {
		event->fillEvent(sdlEvent);
	}
	return ret;
}

int GUIEngine::waitEvent(InputEvent* event) {
	SDL_Event sdlEvent;
	int ret = SDL_WaitEvent(&sdlEvent);
	event->fillEvent(sdlEvent);
	return ret;
}

SurfaceFactory* GUIEngine::getSurfaceFactory(){
	return this->surfaceFactory;
}

void GUIEngine::refreshScreen() {
	SDL_Flip(this->screen);
}

void GUIEngine::drawSurface(SDL_Surface* surface, SDL_Rect* position) {
	SDL_BlitSurface(surface, NULL, this->screen, position);
	this->refreshScreen();
}

void GUIEngine::showSplash() {
	SDL_Surface* splash = SDL_LoadBMP("res/img/splash.bmp");
	SDL_SetColorKey(splash, SDL_RLEACCEL | SDL_SRCCOLORKEY, SDL_MapRGB(splash->format, 255, 255, 255));
	SDL_Rect pos;
	pos.x = (this->screen->w - splash->w) / 2;
	pos.y = (this->screen->h - splash->h) / 2;
	this->drawSurface(splash, &pos);
	SDL_FreeSurface(splash);
}

}
